package com.github.refresh;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.OverScroller;
import android.widget.ScrollView;

import androidx.core.view.ScrollingView;

public class RefreshLayout extends ViewGroup {
    public boolean debug = false;
    private OnCanPullListener onCanPullListener;
    private View canPullChildView;
    private RefreshListener refreshListener;

    public View getCanPullChildView() {
        return canPullChildView;
    }

    public void setCanPullChildView(View canPullChildView) {
        this.canPullChildView = canPullChildView;
    }

    private View getCanScrollChildView(View view){
        if(view instanceof ScrollingView||view instanceof ScrollView||view instanceof AbsListView){
            return view;
        }
        ViewGroup parent=null;
        if(view instanceof ViewGroup){
            parent= (ViewGroup) view;
        }
        if(parent==null){
            return null;
        }
        int childCount = parent.getChildCount();
        if(childCount==0){
            return null;
        }
        for (int i = childCount-1; i >= 0; i--) {
            View childView = getCanScrollChildView(parent.getChildAt(i));
            if(childView!=null){
                return childView;
            }
        }
        return null;
    }
    public void setRefreshListener(RefreshListener refreshListener) {
        this.refreshListener = refreshListener;
    }

    public OnCanPullListener getOnCanPullListener() {
        if(onCanPullListener==null){
            onCanPullListener=new OnCanPullListener() {
                @Override
                public boolean childCanPull() {
                    return false;
                }
            };
        }
        return onCanPullListener;
    }

    public void setOnCanPullListener(OnCanPullListener onCanPullListener) {
        this.onCanPullListener = onCanPullListener;
    }

    private RefreshListener getRefreshListener() {
        if (refreshListener == null) {
            refreshListener = new RefreshListener() {
                @Override
                public void onRefresh(RefreshLayout layout) {

                }
            };
        }
        return refreshListener;
    }

    private RefreshLayoutHelper helper = new RefreshLayoutHelper();

    public RefreshLayoutHelper getHelper() {
        return helper;
    }

    private View headerView;
    private int headerViewHeight;

    private View contentView;
    private ScrollHelper scrollHelper;
    private AutoRefreshScrollHelper autoRefreshScrollHelper;

    private RefreshStatus status = RefreshStatus.DEF;

    public RefreshStatus getStatus() {
        return status;
    }

    public void setStatus(RefreshStatus status) {
        this.status = status;
    }

    private PullDownListener listener;

    private PullDownListener getListener() {
        if (listener == null) {
            listener = new PullDownListener() {
                @Override
                public void pullDownDistance(RefreshLayout layout, PullDown pullDown) {

                }
            };
        }
        return listener;
    }

    public void setListener(PullDownListener listener) {
        this.listener = listener;
    }

    public RefreshLayout(Context context) {
        super(context);
        init(null);
    }

    public RefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public RefreshLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    public RefreshLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(attrs);
    }

    /*如果滑动小于这个距离则不移动视图，在这个滑动距离内判断是垂直滑动还是横向滑动*/
    private int touchSlop;
    //    private boolean allowMoveByTouchSlop;
    private boolean needHorizontalScroll;
    private MotionEvent lastMoveEvent;
    private ViewConfiguration viewConfiguration;
    private boolean isPressDown;

    private void init(AttributeSet attrs) {
        scrollHelper = new ScrollHelper(getContext());
        viewConfiguration = ViewConfiguration.get(getContext());
        touchSlop = (int) (viewConfiguration.getScaledTouchSlop() * 1.5f);

        if (attrs != null) {
            TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.RefreshLayout);
            helper.setAttr(typedArray);
            typedArray.recycle();
        }
    }

    public void setHeaderView(View header) {
        if (headerView != null && header != null && headerView != header) {
            removeView(headerView);
        }
        ViewGroup.LayoutParams lp = header.getLayoutParams();
        if (lp == null) {
            lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            header.setLayoutParams(lp);
        }
        headerView = header;
        addView(header, 0);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int childCount = getChildCount();
        if (childCount <= 0) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        if (headerView == null) {
            if (childCount > 0) {
                headerView = getChildAt(0);
            }
        }
        if (contentView == null) {
            if (childCount > 1) {
                contentView = getChildAt(1);
            }
        }

        if (headerView != null) {
            measureChildWithMargins(headerView, widthMeasureSpec, 0, heightMeasureSpec, 0);
            MarginLayoutParams lp = (MarginLayoutParams) headerView.getLayoutParams();
            headerViewHeight = headerView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;

            helper.setHeaderViewHeight(headerViewHeight);
        }
        int contentWidth = 0;
        int contentHeight = 0;
        if (contentView != null) {
            measureChildWithMargins(contentView, widthMeasureSpec, 0, heightMeasureSpec, 0);

            contentWidth = contentView.getMeasuredWidth();
            contentHeight = contentView.getMeasuredHeight();
        }
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        setMeasuredDimension(
                widthMode == MeasureSpec.EXACTLY ? widthSize : Math.min(widthSize, contentWidth),
                heightMode == MeasureSpec.EXACTLY ? heightSize : Math.min(heightSize, contentHeight)
        );
    }

    private boolean isDebug() {
        return debug;
    }

    private void log(String msg) {
        if (!isDebug()) {
            return;
        }
        Log.i("RefreshLayout", "=====" + msg);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        if (childCount <= 0) {
            return;
        }
        int paddingLeft = getPaddingLeft();
        int paddingTop = getPaddingTop();
        if (headerView != null) {
            MarginLayoutParams lp = (MarginLayoutParams) headerView.getLayoutParams();
            int left = paddingLeft + lp.leftMargin;
            /*因为下拉过程会触发重新绘制操作，所以需要加上下拉距离*/
            int top = -(getPaddingBottom() + lp.bottomMargin + headerView.getMeasuredHeight()) + helper.getCurrentTotalOffsetY();

            headerView.layout(left, top, left + headerView.getMeasuredWidth(), top + headerView.getMeasuredHeight());
        }
        if (contentView != null) {
            MarginLayoutParams lp = (MarginLayoutParams) contentView.getLayoutParams();
            int left = paddingLeft + lp.leftMargin;
            /*因为下拉过程会触发重新绘制操作，所以需要加上下拉距离*/
            int top = paddingTop + lp.topMargin + helper.getCurrentTotalOffsetY();

            contentView.layout(left, top, left + contentView.getMeasuredWidth(), top + contentView.getMeasuredHeight());
        }
    }

    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        return p != null && p instanceof LayoutParams;
    }

    @Override
    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    }

    @Override
    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
        return new LayoutParams(p);
    }

    @Override
    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    /*当显示完刷新成功或者刷新失败的view之后，开始回弹时，正好触发down事件，此时不处理down事件，否则松手不会回弹，因为success或error状态直接return*/
    private void refreshSuccess() {
        if(getHelper().getCurrentTotalOffsetY()==0&&getStatus()==RefreshStatus.DEF){
            /*如果没有下拉距离，可以不改变状态*/
            return;
        }
        setStatus(RefreshStatus.RefreshSuccess);
        if (helper.isRefreshShowSuccess()) {
            if (pullDown == null) {
                pullDown = new PullDown();
            }
            PullDown.reset(pullDown);
            int topDistance = helper.getCurrentTotalOffsetY();
            pullDown.preTopDistance = helper.getPreTotalOffsetY();
            pullDown.topDistance = topDistance;
            pullDown.isPullDown = false;
            pullDown.offsetY = 0;
            pullDown.contentView = contentView;
            pullDown.headerView = headerView;
            pullDown.headerViewHeight = headerView.getMeasuredHeight();
            pullDown.isTouch = isPressDown;
            pullDown.status = getStatus();
            getListener().pullDownDistance(this, pullDown);

            postDelayed(new Runnable() {
                @Override
                public void run() {
                    /*更改当前状态，并回弹*/
                    refreshEnd();
                }
            }, helper.getRefreshResultDurationTime());
        } else {
            /*更改当前状态，并回弹*/
            refreshEnd();
        }

    }

    private void refreshError() {
        if(getHelper().getCurrentTotalOffsetY()==0&&getStatus()==RefreshStatus.DEF){
            /*如果没有下拉距离，可以不改变状态*/
            return;
        }
        setStatus(RefreshStatus.RefreshError);
        if (helper.isRefreshShowError()) {
            if (pullDown == null) {
                pullDown = new PullDown();
            }
            PullDown.reset(pullDown);
            int topDistance = helper.getCurrentTotalOffsetY();
            pullDown.preTopDistance = helper.getPreTotalOffsetY();
            pullDown.topDistance = topDistance;
            pullDown.isPullDown = false;
            pullDown.offsetY = 0;
            pullDown.contentView = contentView;
            pullDown.headerView = headerView;
            pullDown.headerViewHeight = headerView.getMeasuredHeight();
            pullDown.isTouch = isPressDown;
            pullDown.status = getStatus();
            getListener().pullDownDistance(this, pullDown);

            postDelayed(new Runnable() {
                @Override
                public void run() {
                    /*更改当前状态，并回弹*/
                    refreshEnd();
                }
            }, helper.getRefreshResultDurationTime());
        } else {
            /*更改当前状态，并回弹*/
            refreshEnd();
        }
    }

    public void refreshComplete(boolean refreshSuccess) {
        if (refreshSuccess) {
            refreshSuccess();
        } else {
            refreshError();
        }
    }

    private void refreshEnd() {
        if (isPressDown) {
            if (pullDown == null) {
                pullDown = new PullDown();
            }
            PullDown.reset(pullDown);
            int topDistance = helper.getCurrentTotalOffsetY();
            computeStatus(topDistance);
            pullDown.preTopDistance = helper.getPreTotalOffsetY();
            pullDown.topDistance = topDistance;
            pullDown.isPullDown = false;
            pullDown.offsetY = 0;
            pullDown.contentView = contentView;
            pullDown.headerView = headerView;
            pullDown.headerViewHeight = headerView.getMeasuredHeight();
            pullDown.isTouch = isPressDown;
            pullDown.status = getStatus();
            getListener().pullDownDistance(this, pullDown);
        } else {
            backTopForComplete((int) helper.getDurationCloseHeader());
        }
    }


    public static class LayoutParams extends MarginLayoutParams {
        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
        }

        public LayoutParams(int width, int height) {
            super(width, height);
        }

        public LayoutParams(MarginLayoutParams source) {
            super(source);
        }

        public LayoutParams(ViewGroup.LayoutParams source) {
            super(source);
        }
    }


    @Override
    public void addView(View child) {
        if (getChildCount() > 1) {
            throw new IllegalStateException("RefreshLayout can host only two direct child");
        }
        super.addView(child);
    }

    @Override
    public void addView(View child, int index) {
        if (getChildCount() > 1) {
            throw new IllegalStateException("RefreshLayout can host only two direct child");
        }
        super.addView(child, index);
    }

    @Override
    public void addView(View child, ViewGroup.LayoutParams params) {
        if (getChildCount() > 1) {
            throw new IllegalStateException("RefreshLayout can host only two direct child");
        }
        super.addView(child, params);
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        if (getChildCount() > 1) {
            throw new IllegalStateException("RefreshLayout can host only two direct child");
        }
        super.addView(child, index, params);
    }

    public boolean dispatchTouchEventSupper(MotionEvent e) {
        return super.dispatchTouchEvent(e);
    }

    private void sendCancelEvent() {
        /*如果内容可以上下滑动，则滑动结束后ACTION_UP时需要手动发送子view的ACTION_CANCEL事件，防止滑动结束后触发子view的点击事件*/
        if (lastMoveEvent == null) {
            return;
        }
        MotionEvent last = lastMoveEvent;
        MotionEvent e = MotionEvent.obtain(last.getDownTime(), last.getEventTime() /*+ ViewConfiguration.getLongPressTimeout()*/, MotionEvent.ACTION_CANCEL, last.getX(), last.getY(), last.getMetaState());
        dispatchTouchEventSupper(e);
    }

    private void sendDownEvent() {
        sendDownEvent(0);
    }

    private void sendDownEvent(float downY) {
        if (lastMoveEvent == null) {
            return;
        }
        log("sendDownEvent");
        final MotionEvent last = lastMoveEvent;
        MotionEvent e = MotionEvent.obtain(last.getDownTime(), last.getEventTime(), MotionEvent.ACTION_DOWN, last.getX(), last.getY() + downY, last.getMetaState());
        dispatchTouchEventSupper(e);
    }

    private void sendMoveEvent() {
        if (lastMoveEvent == null) {
            return;
        }
        log("sendMoveEvent");
        final MotionEvent last = lastMoveEvent;
        MotionEvent e = MotionEvent.obtain(last.getDownTime(), last.getEventTime(), MotionEvent.ACTION_MOVE, last.getX(), last.getY(), last.getMetaState());
        dispatchTouchEventSupper(e);
    }

    /*记录上一次的move事件x和y值*/
    private float preMoveX;
    private float preMoveY;

    /*触发MOVE事件时不会立即滑动，大于等于开始滑动,滑动前的位置*/
    private float downY;
    private float downX;

    private PullDown pullDown = new PullDown();

    private void sendPullDownEvent(boolean isTouchEvent) {
        sendPullDownEvent(isTouchEvent, 0);
    }

    private void sendPullDownEvent(boolean isTouchEvent, int offsetY) {
        if (getStatus() == RefreshStatus.Refresh
                || getStatus() == RefreshStatus.OpenPage
                || getStatus() == RefreshStatus.RefreshSuccess
                || getStatus() == RefreshStatus.RefreshError
        ) {
            /*如果是刷新中状态，或者其他状态结果的情况*/
            return;
        }

        if (pullDown == null) {
            pullDown = new PullDown();
        }
        PullDown.reset(pullDown);
        int topDistance = helper.getCurrentTotalOffsetY();
        if (isTouchEvent) {
            /*只触摸时计算状态*/
            computeStatus(topDistance);
        }

        pullDown.preTopDistance = helper.getPreTotalOffsetY();
        pullDown.topDistance = topDistance;
        pullDown.isPullDown = offsetY > 0;
        pullDown.offsetY = offsetY;
        pullDown.contentView = contentView;
        pullDown.headerView = headerView;
        pullDown.headerViewHeight = headerView.getMeasuredHeight();
        pullDown.isTouch = isTouchEvent;
        pullDown.status = getStatus();
        getListener().pullDownDistance(this, pullDown);
    }

    private void computeStatus(int topDistance) {
        /*如果下拉的距离很多，则不刷新*/
        if (helper.getPullDownHeaderHeightOpenPage() > helper.getPullDownHeaderHeightRefresh() && topDistance >= helper.getPullDownHeaderHeightOpenPage()) {
            setStatus(RefreshStatus.PreOpenPage);
        } else if (topDistance >= helper.getPullDownHeaderHeightRefresh()) {
            /*如果刷新中，下拉子view,此时刷新成功或者失败了，则不改变下拉状态，等成功失败持续时间结束则改变状态*/
//            if (getStatus() != RefreshStatus.RefreshSuccess && getStatus() != RefreshStatus.RefreshError) {
            setStatus(RefreshStatus.PreRefresh);
//            }
        } else if (topDistance < helper.getPullDownHeaderHeightRefresh() && topDistance > 0) {
            /*如果刷新中，下拉子view,此时刷新成功或者失败了，则不改变下拉状态,等成功失败持续时间结束则改变状态*/
//            if (getStatus() != RefreshStatus.RefreshSuccess && getStatus() != RefreshStatus.RefreshError) {
            setStatus(RefreshStatus.PullDown);
//            }
        } else if (topDistance <= 0) {
            setStatus(RefreshStatus.DEF);
        }
    }
    private void autoGetCanScrollChildView(){
        if(getCanPullChildView()!=null){
            return;
        }
        if(contentView instanceof ScrollingView){

        }else if(contentView instanceof ScrollView){

        }else if(contentView instanceof AbsListView){

        }else{
            if(contentView instanceof ViewGroup){
                setCanPullChildView(getCanScrollChildView((ViewGroup)contentView));
            }
        }
    }
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        autoGetCanScrollChildView();
        if (!isEnabled() || contentView == null || headerView == null) {
            return dispatchTouchEventSupper(ev);
        }
        /*如果自动刷新正好在自动下拉状态，则不触发事件，否者还没自动下拉完毕，就刷新成功，滚动容易冲突*/
        if (autoRefreshScrollHelper != null && autoRefreshScrollHelper.isScrolling()) {
            return true;
        }
        int action = ev.getAction();
        float x;
        float y;
        boolean scrolling;
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                isPressDown = true;
//                allowMoveByTouchSlop = false;
                needHorizontalScroll = false;
                x = ev.getX();
                y = ev.getY();
                helper.setPreEventPoint(x, y);
                preMoveX = x;
                preMoveY = y;
                downX = x;
                downY = y;
                sendPullDownEvent(true);

                if (getStatus() == RefreshStatus.OpenPage) {
                    /*打开其他页面、刷新成功、刷新失败回弹结束前不响应事件*/
                    return true;
                }
                scrollHelper.stopScroller();
                scrolling = scrollHelper.isScrolling();
                if (getStatus() == RefreshStatus.RefreshSuccess || getStatus() == RefreshStatus.RefreshError) {
                    //显示成功或者失败view时可以点击
                    dispatchTouchEventSupper(ev);
                    return true;
                }

                /*如果内容可以上下滑动，则滑动结束后ACTION_UP时需要手动发送子view的ACTION_CANCEL事件，
                因为down事件调用了dispatchTouchEventSupper方法，可能下发给子view了，防止滑动结束后触发子view的点击事件*/
                if (helper.getCurrentTotalOffsetY() > 0) {
                    /*如果子view处于下拉状态，此时down事件不分发给子view，除非是刷新中的状态*/
                    if (getStatus() == RefreshStatus.Refresh && !scrolling || (helper.getCurrentTotalOffsetY() <= 20 + headerViewHeight)) {
                        /*加载中且回弹结束或者快要回弹结束让子view触发down事件*/
                        dispatchTouchEventSupper(ev);
                    }
                } else {
                    /*需要将down事件传递下去，否则子view无法触发事件*/
                    dispatchTouchEventSupper(ev);
                }
                return true;
            case MotionEvent.ACTION_MOVE:
                lastMoveEvent = ev;
                x = ev.getX();
                y = ev.getY();
                float tempX = preMoveX;
                float tempY = preMoveY;
                /*下滑子view时，需要更新move事件的x,y值,保证currentTotalOffsetY正确，否者子view下滑到头之后，view会突然下滑很多距离*/
                helper.setPreEventPoint(tempX, tempY);
                preMoveX = x;
                preMoveY = y;

                if (getStatus() == RefreshStatus.OpenPage) {
                    /*如果释放打开其他页面，不做移动处理，如果回弹持续时间长，这个时候可以移动，会有问题*/
                    /*回弹过程中，往上移动,触发子view上滑，这个时候再往下移动子view无法移动，因为down事件没有下发给子view，所以回弹过程view不做移动处理*/
                    return true;
                }
                //region------------------如果下滑时，判断子view是否可以向下滑动------------------
                if (y - tempY > 0 && contentViewCanScrollDown()) {
                    /*如果子view可以向下移动*/
                    return dispatchTouchEventSupper(ev);
                }
                //endregion

                log("ACTION_MOVE,x=" + x + ",y=" + y + ",preMoveX" + preMoveX + ",getCurrentTotalOffsetY" + helper.getCurrentTotalOffsetY());

                //region------------------判断滑动距离是否满足滑动view的条件------------------

                    /*如果需要处理横向滑动冲突*/
                if (helper.isNeedHorizontalScroll() && !needHorizontalScroll && Math.abs(x - downX) < touchSlop) {
                    if(helper.getCurrentTotalOffsetY()==0){
                        /*需要判断是否处理子view横向滑动*/
                        if ((Math.abs((x - downX) / (y - downY)) >= helper.getHorizontalScrollXYRatio() || (y == downY && x != downX))) {
                            needHorizontalScroll = true;
                        }
                    }
                }
                if (helper.isNeedHorizontalScroll() && needHorizontalScroll) {
                    return dispatchTouchEventSupper(ev);
                }

                //endregion

                helper.move(x, y);
//                allowMoveByTouchSlop = true;
                float offsetY = helper.getOffsetY();
                log("-------------------------------------");
                log("ACTION_MOVE,x=" + x + ",y=" + y + ",offsetY" + offsetY);
                log("-------------------------------------");
                boolean moveDown = offsetY > 0;
                boolean canMoveUp = helper.canMoveUp();
                if (moveDown || (canMoveUp)) {
                    /*如果向下或者向上移动了子view,此时需要取消子view的事件，否则可能触发子view的长按事件*/
                    if ((int) offsetY != 0) {
                        sendCancelEvent();
                    }
                    /*开始移动视图*/
                    moveView((int) offsetY);
                    return true;
                }
                return dispatchTouchEventSupper(ev);
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (getStatus() == RefreshStatus.OpenPage) {
                    /*如果释放打开其他页面，不做移动处理，如果回弹持续时间长，这个时候可以移动，会有问题*/
                    /*回弹过程中，往上移动,触发子view上滑，这个时候再往下移动子view无法移动，因为down事件没有下发给子view，所以回弹过程view不做移动处理*/
                    return true;
                }
                scrolling = scrollHelper.isScrolling();
                isPressDown = false;
                release();
                sendPullDownEvent(false, 0);
                int totalOffsetY = helper.getCurrentTotalOffsetY();
                log("totalOffsetY==" + totalOffsetY);
                if (totalOffsetY >= 0) {
                    /*如果有下滑距离，则松手之后回弹*/
                    if (getStatus() == RefreshStatus.PullDown || getStatus() == RefreshStatus.RefreshSuccess || getStatus() == RefreshStatus.RefreshError) {
                        int duration = (int) (totalOffsetY * helper.getDurationCloseHeader() / headerViewHeight);
                        backTopForComplete((int) Math.min(duration, helper.getDurationCloseHeader()));
                    } else if (getStatus() == RefreshStatus.OpenPage) {
                        /*打开其他页面头view回弹*/
                        backTopForComplete((int) helper.getDurationCloseForOpenPage());
                    } else if (getStatus() == RefreshStatus.Refresh) {
                        backTopForRefresh();
                    }
                    /*如果向下移动了子view,此时需要取消子view的事件，否则在ACTION_UP的时候可能触发子view的长按或者点击事件(开发阶段未加回弹动画时复现)*/
//                    sendCancelEvent();
                    /*如果当前时刷新状态，且scroller为结束，则不能分发给子view事件*/
                    if (!scrolling) {
                        dispatchTouchEventSupper(ev);
                    }
                    return true;
                }
                return dispatchTouchEventSupper(ev);
        }
        return dispatchTouchEventSupper(ev);
    }

    private void release() {
        /*释放时，可能存在多种情况*/
        /*如果释放时，已经在刷新中,或者其他某种结果时返回*/
        if (getStatus() == RefreshStatus.Refresh
                || getStatus() == RefreshStatus.OpenPage
                || getStatus() == RefreshStatus.RefreshSuccess
                || getStatus() == RefreshStatus.RefreshError
        ) {
            return;
        }
        int topDistance = helper.getCurrentTotalOffsetY();
        if (topDistance <= 0) {
            setStatus(RefreshStatus.DEF);
        } else if (helper.getPullDownHeaderHeightOpenPage() > helper.getPullDownHeaderHeightRefresh() && topDistance >= helper.getPullDownHeaderHeightOpenPage()) {
            setStatus(RefreshStatus.OpenPage);
            getRefreshListener().onOpenPage(this);
        } else if (topDistance >= helper.getPullDownHeaderHeightRefresh()) {
            setStatus(RefreshStatus.Refresh);
            getRefreshListener().onRefresh(this);
        }


        if (pullDown == null) {
            pullDown = new PullDown();
        }
        PullDown.reset(pullDown);
        pullDown.preTopDistance = helper.getPreTotalOffsetY();
        pullDown.topDistance = topDistance;
        pullDown.isPullDown = false;
        pullDown.offsetY = 0;
        pullDown.contentView = contentView;
        pullDown.headerView = headerView;
        pullDown.headerViewHeight = headerView.getMeasuredHeight();
        pullDown.isTouch = false;
        pullDown.status = getStatus();
        getListener().pullDownDistance(this, pullDown);
    }

    private boolean contentViewCanScrollDown() {
        if (contentView == null) {
            log("=======contentViewCanScrollDown:false");
            return false;
        }
        boolean b = contentView.canScrollVertically(-1);
        if(b){
            return true;
        }
        if(getCanPullChildView()!=null&&getCanPullChildView().canScrollVertically(-1)){
            return true;
        }
        if(getOnCanPullListener().childCanPull()){
            return true;
        }
        log("=======contentViewCanScrollDown:" + b);
        return false;
    }

    private void moveView(int offsetY) {
        moveView(true, offsetY);
    }

    /***
     *
     * @param isTouchEvent  true触摸滑动
     * @param offsetY       滑动距离
     */
    private void moveView(boolean isTouchEvent, int offsetY) {

        /*moveView的参数必须要int类型，如果是float，则移动(offsetTopAndBottom)会有误差*/
        if (offsetY == 0) {
            return;
        }
        int needDispatchEventToChild = -1;
        int totalOffsetY = helper.getCurrentTotalOffsetY();
        if (offsetY > 0) {
            /*向下移动view*/
        } else {
            /*向上移动view*/
            if (Math.abs(offsetY) > totalOffsetY) {
                offsetY = -totalOffsetY;
                /*如果向上移动量大于等于总偏移量，需要分发给子view down事件，随后子view也可以进行滑动*/
                needDispatchEventToChild = offsetY + totalOffsetY;
            } else if (Math.abs(offsetY) == totalOffsetY) {
                needDispatchEventToChild = 0;
            }

        }
        helper.setCurrentTotalOffsetY(totalOffsetY + offsetY);


        if (headerView != null) {
            headerView.offsetTopAndBottom(offsetY);
        }
        if (contentView != null) {
            contentView.offsetTopAndBottom(offsetY);
        }
        if (isTouchEvent) {
            if (needDispatchEventToChild >= 0) {
                /*如果向上移动子view，到顶之后需要把down事件和move事件传递给子view*/
                /*这里需要往下加点偏移量，否则到顶时不松手继续移动子view会有停顿感*/
                sendDownEvent();
//                sendMoveEvent();
            }
        }

        sendPullDownEvent(isTouchEvent, offsetY);
//        invalidate();

    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (scrollHelper != null) {
            scrollHelper.destroy();
        }
        if (autoRefreshScrollHelper != null) {
            autoRefreshScrollHelper.destroy();
        }
    }

    /*自动刷新*/
    public void autoRefresh() {
        if (autoRefreshScrollHelper == null) {
            autoRefreshScrollHelper = new AutoRefreshScrollHelper(getContext());
        }
        if (getStatus() == RefreshStatus.Refresh || autoRefreshScrollHelper.isScrolling()) {
            return;
        }

        setStatus(RefreshStatus.Refresh);

        if (pullDown == null) {
            pullDown = new PullDown();
        }
        PullDown.reset(pullDown);
        pullDown.preTopDistance = helper.getPreTotalOffsetY();
        pullDown.topDistance = helper.getCurrentTotalOffsetY();
        pullDown.isPullDown = true;
        pullDown.offsetY = 0;
        pullDown.contentView = contentView;
        pullDown.headerView = headerView;
        pullDown.headerViewHeight = headerView.getMeasuredHeight();
        pullDown.isTouch = false;
        pullDown.isAutoRefresh = true;
        pullDown.status = getStatus();
        getListener().pullDownDistance(RefreshLayout.this, pullDown);

        autoRefreshScrollHelper.autoPullDown(headerViewHeight, 200);
    }

    /*松手之后刷新*/
    private void backTopForRefresh() {
        int currentTotalOffsetY = helper.getCurrentTotalOffsetY();
        if (scrollHelper != null) {
            if (helper.isRefreshKeepHeader()) {
                int moveDistance = currentTotalOffsetY - helper.getHeaderViewHeight();
                if (moveDistance < 0) {
                    /*如果刷新时，手动向上滑动*/
                    moveDistance = currentTotalOffsetY;
                }
                /*刷新时保持头部view*/
                scrollHelper.backTop(moveDistance, (int) helper.getDurationClose());
            } else {
                scrollHelper.backTop(currentTotalOffsetY, (int) helper.getDurationClose());
            }
        }
    }

    /*松手之后回到顶部*/
    private void backTopForComplete(int duration) {
        int currentTotalOffsetY = helper.getCurrentTotalOffsetY();
        if (scrollHelper != null) {
            scrollHelper.backTop(currentTotalOffsetY, duration);
        }
    }


    class ScrollHelper implements Runnable {
        private OverScroller scroller;
        private boolean isScrolling;

        public ScrollHelper(Context context) {
            this.scroller = new OverScroller(context);
        }

        public void destroy() {
            stopScroller();
        }

        public void stopScroller() {
            if (!scroller.isFinished()) {
                scroller.forceFinished(true);
            }
            isScrolling = false;
            removeCallbacks(this);
        }

        public boolean isScrolling() {
            return isScrolling;
        }

        public void backTop(int topOffset, int duration) {
            if (scroller == null) {
                return;
            }
            if (!scroller.isFinished()) {
                scroller.forceFinished(true);
            }
            isScrolling = true;
            scroller.startScroll(0, helper.getCurrentTotalOffsetY(), 0, -topOffset, duration);
            post(this);
        }

        @Override
        public void run() {
            if (!isScrolling) {
                return;
            }
            if (scroller == null) {
                return;
            }
            int currY = scroller.getCurrY();
            log("run===" + currY);
            boolean computeScrollOffset = scroller.computeScrollOffset();
            if (computeScrollOffset) {
                moveView(false, currY - helper.getCurrentTotalOffsetY());
                post(this);
            } else {
                isScrolling = false;
                /*可能是刷新中，刷新不显示header的情况*/
                /*如果不是刷新中*/
                if (getStatus() != RefreshStatus.Refresh) {
                    /*下拉回弹结束,可能是刷新回弹结束，可能是下拉回弹结束*/
                    if (getStatus() == RefreshStatus.PullDown
                            || getStatus() == RefreshStatus.OpenPage
                            || getStatus() == RefreshStatus.RefreshSuccess
                            || getStatus() == RefreshStatus.RefreshError) {
                        if (currY == 0) {
                            /*此处调试可能有误差，currY==0时，CurrentTotalOffsetY可能为1*/
                            helper.setCurrentTotalOffsetY(0);
                        }
                        if (helper.getCurrentTotalOffsetY() > 0 && currY > 0) {
                            /*有可能时刷新结束时滚动结束，此时不做状态回调处理，等刷新成功view回弹结束才改变状态*/
                            return;
                        }
                        /*或者打开其他页面回弹结束*/
                        setStatus(RefreshStatus.DEF);
                        if (pullDown == null) {
                            pullDown = new PullDown();
                        }
                        PullDown.reset(pullDown);
                        pullDown.preTopDistance = helper.getPreTotalOffsetY();
                        pullDown.topDistance = helper.getCurrentTotalOffsetY();
                        pullDown.isPullDown = false;
                        pullDown.offsetY = 0;
                        pullDown.contentView = contentView;
                        pullDown.headerView = headerView;
                        pullDown.headerViewHeight = headerView.getMeasuredHeight();
                        pullDown.isTouch = false;
                        pullDown.status = getStatus();
                        getListener().pullDownDistance(RefreshLayout.this, pullDown);
                    }
                }
            }
        }
    }


    class AutoRefreshScrollHelper implements Runnable {
        private OverScroller scroller;
        private boolean isScrolling;

        public AutoRefreshScrollHelper(Context context) {
            this.scroller = new OverScroller(context);
        }

        public void destroy() {
            stopScroller();
        }

        public void stopScroller() {
            if (!scroller.isFinished()) {
                scroller.forceFinished(true);
            }
            isScrolling = false;
            removeCallbacks(this);
        }

        public boolean isScrolling() {
            return isScrolling;
        }

        public void autoPullDown(int topOffset, int duration) {
            if (scroller == null) {
                return;
            }
            if (!scroller.isFinished()) {
                scroller.forceFinished(true);
            }
            isScrolling = true;
            scroller.startScroll(0, helper.getCurrentTotalOffsetY(), 0, topOffset, duration);
            post(this);
        }

        @Override
        public void run() {
            if (!isScrolling) {
                return;
            }
            if (scroller == null) {
                return;
            }
            int currY = scroller.getCurrY();
            log("AutoRefreshScrollHelper==run===" + currY);
            boolean computeScrollOffset = scroller.computeScrollOffset();
            if (computeScrollOffset) {
                moveView(false, currY - helper.getCurrentTotalOffsetY());
                post(this);
            } else {
                /*如果自动下拉完成，触发刷新回调*/
                isScrolling = false;
                getRefreshListener().onRefresh(RefreshLayout.this);
            }
        }
    }
}